package com.mazewei.dev.service;

import com.mazewei.dev.dao.TeacherDao;
import com.mazewei.dev.dao.CourseDao;
import com.mazewei.dev.dao.ClassDao;
import com.mazewei.dev.entity.Teacher;
import com.mazewei.dev.entity.Course;
import com.mazewei.dev.entity.Class;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.opencsv.CSVReader;
import com.opencsv.CSVWriter;
import java.io.StringReader;
import java.io.StringWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 文件上传服务 - 使用Apache POI
 * 处理Excel文件的上传、解析和转换
 * 数据格式：第一列为科目名称，第一行为班级名称，交叉处为教师名字
 */
@Service
public class FileUploadService {
    private static final Logger logger = LoggerFactory.getLogger(FileUploadService.class);
    
    private static final String UPLOAD_DIR = "uploads";
    private static final String OUTPUT_DIR = "output";
    
    private String uploadDir;
    private String outputDir;
    
    @Autowired
    private TeacherDao teacherDao;
    
    @Autowired
    private CourseDao courseDao;
    
    @Autowired
    private ClassDao classDao;
    
    @Autowired
    private CourseMatchingService courseMatchingService;
    
    @Autowired
    private GradeExtractionService gradeExtractionService;
    
    @Autowired
    private ClassMatchingService classMatchingService;
    
    @Autowired
    private TeacherMatchingService teacherMatchingService;
    
    public FileUploadService() {
        // 使用项目根目录下的uploads和output目录
        String projectRoot = System.getProperty("user.dir");
        this.uploadDir = projectRoot + File.separator + UPLOAD_DIR;
        this.outputDir = projectRoot + File.separator + OUTPUT_DIR;
    }
    
    // 移除静态课程映射表，改为完全从数据库获取课程编号

    /**
     * 处理Excel文件上传和转换
     * @param file 上传的文件
     * @param startCol 起始列
     * @param endCol 结束列
     * @param startRow 起始行
     * @param endRow 结束行
     * @param schoolSection 学部选择（primary=小学部，middle=初中部）
     * @param dataMode 数据处理模式（normal=普通模式，strict=严格模式）
     * @return 处理结果
     */
    public Map<String, Object> processExcel(MultipartFile file, String startCol, String endCol, int startRow, int endRow, String schoolSection, String dataMode) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 验证文件
            if (!isValidExcelFile(file)) {
                result.put("success", false);
                result.put("message", "无效的Excel文件格式");
                return result;
            }
            
            // 创建目录
            createDirectories();
            
            // 保存上传的文件
            String fileName = saveUploadedFile(file);
            String filePath = Paths.get(uploadDir, fileName).toString();
            
            // 处理Excel文件
            logger.info("开始处理Excel文件: {}, 参数: startCol={}, endCol={}, startRow={}, endRow={}, schoolSection={}, dataMode={}", filePath, startCol, endCol, startRow, endRow, schoolSection, dataMode);
            List<Map<String, Object>> processedData = processExcelFile(filePath, startCol, endCol, startRow, endRow, schoolSection, dataMode);
            logger.info("Excel文件处理完成，共处理 {} 行数据", processedData.size());
            
            if (processedData.isEmpty()) {
                result.put("success", false);
                result.put("message", "未找到有效数据，请检查文件格式和参数设置");
                return result;
            }
            
            // 生成输出文件
            logger.info("开始生成输出文件，处理数据条数: {}", processedData.size());
            boolean isStrictMode = "strict".equals(dataMode);
            String outputFileName = generateOutputFile(processedData, fileName, isStrictMode);
            logger.info("输出文件生成完成: {}", outputFileName);
            
            // 验证输出文件是否存在
            Path outputFilePath = Paths.get(outputDir, outputFileName);
            if (Files.exists(outputFilePath)) {
                logger.info("输出文件验证成功，文件大小: {} bytes", Files.size(outputFilePath));
            } else {
                logger.error("输出文件生成失败，文件不存在: {}", outputFilePath);
                throw new IOException("输出文件生成失败");
            }
            
            result.put("success", true);
            result.put("message", "文件处理成功");
            result.put("processedCount", processedData.size());
            result.put("outputFile", outputFileName);
            result.put("outputFilePath", outputFilePath.toString());
            result.put("downloadUrl", "/api/download/" + outputFileName);
            
            // 清理临时文件
            cleanupTempFile(filePath);
            
        } catch (Exception e) {
            logger.error("处理Excel文件时发生错误: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "处理文件时发生错误: " + e.getMessage());
            result.put("error", e.getClass().getSimpleName());
        }
        
        return result;
    }

    /**
     * 处理多工作表Excel文件
     *
     * @param file       上传的文件
     * @param sheetNames 工作表名称数组
     * @param startCol   起始列
     * @param endCol     结束列
     * @param startRow   起始行
     * @param endRow     结束行
     * @return 处理结果
     */
    public Map<String, Object> processMultiSheetExcel(MultipartFile file, String[] sheetNames,
                                                      String startCol, String endCol, int startRow, int endRow) {
        return processMultiSheetExcel(file, sheetNames, startCol, endCol, startRow, endRow, "primary", "strict");
    }
    
    /**
     * 处理多工作表Excel文件（支持学部选择）
     *
     * @param file       上传的文件
     * @param sheetNames 工作表名称数组
     * @param startCol   起始列
     * @param endCol     结束列
     * @param startRow   起始行
     * @param endRow     结束行
     * @param schoolSection 学部选择（primary=小学部，middle=初中部）
     * @param dataMode 数据处理模式（normal=普通模式，strict=严格模式）
     * @return 处理结果
     */
    public Map<String, Object> processMultiSheetExcel(MultipartFile file, String[] sheetNames,
                                                      String startCol, String endCol, int startRow, int endRow, String schoolSection, String dataMode) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 验证文件
            if (!isValidExcelFile(file)) {
                result.put("success", false);
                result.put("message", "无效的Excel文件格式");
                return result;
            }
            
            // 创建目录
            createDirectories();
            
            // 保存上传的文件
            String fileName = saveUploadedFile(file);
            String filePath = Paths.get(uploadDir, fileName).toString();
            
            // 处理多工作表
            Map<String, Object> processResult = processMultiSheets(filePath, sheetNames, startCol, endCol, startRow, endRow, schoolSection, dataMode);
            
            result.putAll(processResult);
            
            // 获取所有处理的数据
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> allData = (List<Map<String, Object>>) processResult.get("allData");
            
            if (allData != null && !allData.isEmpty()) {
                // 生成输出文件
                boolean isStrictMode = "strict".equals(dataMode);
                String outputFileName = generateOutputFile(allData, fileName, isStrictMode);
                logger.info("输出文件生成完成: {}", outputFileName);
                
                // 验证输出文件
                Path outputFilePath = Paths.get(outputDir, outputFileName);
                if (Files.exists(outputFilePath)) {
                    logger.info("输出文件验证成功，文件大小: {} bytes", Files.size(outputFilePath));
                } else {
                    logger.error("输出文件生成失败，文件不存在: {}", outputFilePath);
                }
                
                // 添加输出文件信息到结果
                result.put("outputFile", outputFileName);
                result.put("outputFilePath", outputFilePath.toString());
                result.put("downloadUrl", "/api/download/" + outputFileName);
            }
            
            result.put("success", true);
            result.put("message", "多工作表处理完成");
            
            // 清理临时文件
            cleanupTempFile(filePath);
            
        } catch (Exception e) {
            logger.error("处理多工作表Excel文件时发生错误", e);
            result.put("success", false);
            result.put("message", "处理文件时发生错误: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 处理多个工作表
     * @param filePath 文件路径
     * @param sheetNames 工作表名称数组
     * @param startCol 起始列
     * @param endCol 结束列
     * @param startRow 起始行
     * @param endRow 结束行
     * @return 处理结果
     */

    
    /**
     * 处理多个工作表（支持学部选择）
     * @param filePath 文件路径
     * @param sheetNames 工作表名称数组
     * @param startCol 起始列
     * @param endCol 结束列
     * @param startRow 起始行
     * @param endRow 结束行
     * @param schoolSection 学部选择（primary=小学部，middle=初中部）
     * @param dataMode 数据处理模式（normal=普通模式，strict=严格模式）
     * @return 处理结果
     */
    public Map<String, Object> processMultiSheets(String filePath, String[] sheetNames, 
                                                  String startCol, String endCol, int startRow, int endRow, String schoolSection, String dataMode) {
        Map<String, Object> result = new HashMap<>();
        List<String> processedSheets = new ArrayList<>();
        List<String> notFoundSheets = new ArrayList<>();
        List<Map<String, Object>> allProcessedData = new ArrayList<>();
        
        try (Workbook workbook = createWorkbook(filePath)) {
            
            for (String sheetName : sheetNames) {
                Sheet sheet = null;
                String actualSheetName = sheetName;
                
                // 检查是否为数字索引（从1开始）
                try {
                    int sheetIndex = Integer.parseInt(sheetName.trim());
                    if (sheetIndex > 0 && sheetIndex <= workbook.getNumberOfSheets()) {
                        sheet = workbook.getSheetAt(sheetIndex - 1); // 转换为0基索引
                        actualSheetName = sheet.getSheetName();
                        logger.info("使用索引 {} 获取工作表: {}", sheetIndex, actualSheetName);
                    }
                } catch (NumberFormatException e) {
                    // 不是数字，按名称查找
                    sheet = workbook.getSheet(sheetName);
                }
                
                if (sheet != null) {
                    List<Map<String, Object>> sheetData = processSheet(sheet, startCol, endCol, startRow, endRow, schoolSection, dataMode);
                    allProcessedData.addAll(sheetData);
                    processedSheets.add(actualSheetName);
                    logger.info("成功处理工作表: {}, 数据行数: {}", actualSheetName, sheetData.size());
                } else {
                    notFoundSheets.add(sheetName);
                    logger.warn("未找到工作表: {}", sheetName);
                }
            }
            
            result.put("totalProcessed", processedSheets.size());
            result.put("requestedSheets", sheetNames.length);
            result.put("processedSheets", processedSheets);
            result.put("notFoundSheets", notFoundSheets);
            result.put("allData", allProcessedData);
            
        } catch (Exception e) {
            logger.error("处理多工作表时发生错误", e);
            throw new RuntimeException("处理多工作表失败: " + e.getMessage(), e);
        }
        
        return result;
    }

    /**
     * 处理Excel文件
     * @param filePath 文件路径
     * @param startCol 起始列
     * @param endCol 结束列
     * @param startRow 起始行
     * @param endRow 结束行
     * @return 处理后的数据
     */

    
    public List<Map<String, Object>> processExcelFile(String filePath, String startCol, String endCol, int startRow, int endRow, String schoolSection, String dataMode) {
        List<Map<String, Object>> result = new ArrayList<>();
        
        try (Workbook workbook = createWorkbook(filePath)) {
            
            Sheet sheet = workbook.getSheetAt(0); // 使用第一个工作表
            result = processSheet(sheet, startCol, endCol, startRow, endRow, schoolSection, dataMode);
            
        } catch (Exception e) {
            logger.error("处理Excel文件时发生错误: {}", filePath, e);
            throw new RuntimeException("处理Excel文件失败: " + e.getMessage(), e);
        }
        
        return result;
    }

    /**
     * 处理工作表
     * @param sheet 工作表
     * @param startCol 起始列
     * @param endCol 结束列
     * @param startRow 起始行
     * @param endRow 结束行
     * @param schoolSection 学部选择（primary=小学部，middle=初中部）
     * @param dataMode 数据处理模式（normal=普通模式，strict=严格模式）
     * @return 处理后的数据
     */
    private List<Map<String, Object>> processSheet(Sheet sheet, String startCol, String endCol, int startRow, int endRow, String schoolSection, String dataMode) {
        List<Map<String, Object>> result = new ArrayList<>();
        
        logger.info("[表格处理开始] 开始处理Excel表格数据");
        
        int startColIndex = convertColumnToIndex(startCol);
        int endColIndex = convertColumnToIndex(endCol);
        
        // 读取表头行的班级名称（通常是第一行，但要根据startRow-1来确定）
        int headerRowIndex = Math.max(0, startRow - 1);
        Row headerRow = sheet.getRow(headerRowIndex);
        List<String> classNames = new ArrayList<>();
        if (headerRow != null) {
            logger.info("[班级信息读取开始] 读取表头行 {} 的班级名称，列范围: {} 到 {}", headerRowIndex + 1, startCol, endCol);
            for (int colIndex = startColIndex; colIndex <= endColIndex; colIndex++) {
                Cell cell = headerRow.getCell(colIndex);
                String className = getCellValueAsString(cell);
                 className = className != null ? className.trim() : "";
                // 保存原始班级名称，稍后根据学部进行格式转换
                classNames.add(className);
                logger.info("[班级信息] 列 {} ({}): {}", getColumnName(colIndex), colIndex, className);
            }
            logger.info("[班级信息读取成功] 共读取到{}个班级: {}", classNames.size(), classNames);
        } else {
            logger.error("[表格处理失败] 未找到表头行: {}", headerRowIndex + 1);
        }
        
        // 处理数据行
        logger.info("开始处理数据行，范围: {} 到 {}", startRow, endRow);
        for (int rowIndex = startRow; rowIndex <= Math.min(endRow, sheet.getLastRowNum()); rowIndex++) {
            Row row = sheet.getRow(rowIndex);
            if (row == null) {
                logger.debug("跳过空行: {}", rowIndex + 1);
                continue;
            }
            
            // 读取第一列的科目名称
            Cell subjectCell = row.getCell(0);
            String subjectName = getCellValueAsString(subjectCell);
            if (subjectName == null || subjectName.trim().isEmpty()) {
                logger.debug("跳过没有科目名称的行: {}", rowIndex + 1);
                continue; // 跳过没有科目名称的行
            }
            
            subjectName = subjectName.trim();
            
            // 检查是否为严格模式且包含@符号
            boolean isStrictMode = "strict".equals(dataMode) && subjectName.contains("@");
            String subjectCode = null;
            String actualSubjectName = subjectName;
            
            if (isStrictMode) {
                // 严格模式：解析@符号分隔的课程编号和课程名称
                String[] parts = subjectName.split("@", 2);
                if (parts.length == 2) {
                    subjectCode = parts[0].trim(); // 课程编号
                    actualSubjectName = parts[1].trim(); // 课程名称
                    logger.info("[严格模式] 第{}行 - 解析课程编号: {}, 课程名称: {}", rowIndex + 1, subjectCode, actualSubjectName);
                } else {
                    logger.warn("[严格模式] 第{}行 - @符号格式不正确，跳过: {}", rowIndex + 1, subjectName);
                    continue;
                }
            } else {
                // 普通模式：进行课程名称转换
                actualSubjectName = courseMatchingService.convertSubjectNameOnRead(subjectName);
            }
            
            logger.debug("处理第 {} 行，科目: {} (模式: {})", rowIndex + 1, actualSubjectName, dataMode);
            
            // 处理每一列的教师数据
            int processedCellsInRow = 0;
            int emptyCellsInRow = 0;
            
            for (int colIndex = startColIndex; colIndex <= endColIndex && colIndex < classNames.size() + startColIndex; colIndex++) {
                Cell teacherCell = row.getCell(colIndex);
                String teacherName = getCellValueAsString(teacherCell);
                
                if (teacherName != null && !teacherName.trim().isEmpty()) {
                    teacherName = teacherName.trim();
                    // 去除教师姓名后面的数字
                    teacherName = teacherMatchingService.removeNumbersFromTeacherName(teacherName);
                    String className = classNames.get(colIndex - startColIndex);
                    
                    logger.info("[数据处理开始] 第{}行第{}列 - 科目: {}, 班级: {}, 教师: {}", 
                               rowIndex + 1, getColumnName(colIndex), actualSubjectName, className, teacherName);
                    
                    // 根据模式获取学科编码和班级信息
                    String finalSubjectCode;
                    String finalSubjectName;
                    String finalClassCode = null;
                    String finalClassName = className;
                    
                    if (isStrictMode) {
                        // 严格模式：直接使用解析出的课程编号和名称
                        finalSubjectCode = subjectCode;
                        finalSubjectName = actualSubjectName;
                        logger.debug("[严格模式] 使用解析的课程编号: {}, 课程名称: {}", finalSubjectCode, finalSubjectName);
                        
                        // 严格模式下处理班级编号和名称
                        if (className.contains("@")) {
                            String[] classParts = className.split("@", 2);
                            if (classParts.length == 2) {
                                finalClassCode = classParts[0].trim(); // 班级编号
                                finalClassName = classParts[1].trim(); // 班级名称
                                logger.debug("[严格模式] 解析班级编号: {}, 班级名称: {}", finalClassCode, finalClassName);
                            }
                        }
                    } else {
                        // 普通模式：使用支持年级识别的方法获取学科编码
                        finalSubjectCode = courseMatchingService.getCourseCodeWithGrade(actualSubjectName, className);
                        finalSubjectName = actualSubjectName; // 默认使用转换后的名称
                        if (finalSubjectCode != null && !finalSubjectCode.isEmpty()) {
                            // 根据课程编号获取数据库中的实际课程名称
                            Course dbCourse = courseDao.findByCourNum(finalSubjectCode);
                            if (dbCourse != null && dbCourse.getCourName() != null) {
                                finalSubjectName = dbCourse.getCourName();
                                logger.debug("使用数据库中的实际课程名称: {} -> {}", actualSubjectName, finalSubjectName);
                            }
                        }
                    }
                    String actualClassName = finalClassName; // 使用处理后的班级名称
                    
                    // 获取教师编号和班级编号
                    String teacherCode = teacherMatchingService.getTeacherCode(teacherName);
                    String classCode;
                    if (isStrictMode && finalClassCode != null) {
                        // 严格模式：直接使用解析出的班级编号
                        classCode = finalClassCode;
                        logger.debug("[严格模式] 使用解析的班级编号: {}", classCode);
                    } else {
                        // 普通模式：通过数据库查找班级编号
                        classCode = classMatchingService.getClassCode(className);
                    }
                    
                    Map<String, Object> record = new HashMap<>();
                    if (isStrictMode) {
                        // 严格模式：返回输入数据的原始内容
                        record.put("subject", finalSubjectName);  // 课程名称：@符号之后的内容
                        record.put("subjectCode", finalSubjectCode);  // 课程编号：@符号之前的内容
                        record.put("className", actualClassName);  // 班级名称：@符号之后的内容
                        record.put("classCode", finalClassCode != null ? finalClassCode : classCode);  // 班级编号：@符号之前的内容
                    } else {
                        // 普通模式：返回转换后的内容
                        record.put("subject", finalSubjectName);
                        record.put("subjectCode", finalSubjectCode);
                        record.put("className", actualClassName);
                        record.put("classCode", classCode);
                    }
                    record.put("teacherName", teacherName);
                    record.put("teacherCode", teacherCode);
                    record.put("row", rowIndex + 1);
                    record.put("col", getColumnName(colIndex));
                    
                    // 转换班级格式：一（1）班 -> 一年1班，根据学部选择调整格式
                    String convertedClassName;
                    if (isStrictMode) {
                        // 严格模式：使用解析后的班级名称进行格式转换
                        convertedClassName = classMatchingService.convertClassFormat(actualClassName, schoolSection);
                    } else {
                        // 普通模式：使用原始班级名称进行格式转换
                        convertedClassName = classMatchingService.convertClassFormat(className, schoolSection);
                    }
                    record.put("convertedClassName", convertedClassName);
                    
                    result.add(record);
                    processedCellsInRow++;
                    
                    logger.info("[数据处理成功] 位置: {}行{}列, 科目编号: {}, 教师编号: {}, 班级编号: {}", 
                               rowIndex + 1, getColumnName(colIndex), finalSubjectCode, teacherCode, classCode);
                } else {
                    emptyCellsInRow++;
                    logger.debug("[数据处理跳过] 第{}行第{}列为空", rowIndex + 1, getColumnName(colIndex));
                }
            }
            
            logger.info("[行处理完成] 第{}行 - 科目: {}, 处理单元格: {}, 空单元格: {}", 
                       rowIndex + 1, actualSubjectName, processedCellsInRow, emptyCellsInRow);
        }
        
        // 统计处理结果
        long completeRecords = result.stream().mapToLong(record -> 
            (Boolean) record.getOrDefault("isComplete", false) ? 1 : 0).sum();
        long incompleteRecords = result.size() - completeRecords;
        
        logger.info("[表格处理完成] 总记录数: {}, 完整记录: {}, 不完整记录: {}", 
                   result.size(), completeRecords, incompleteRecords);
        
        if (incompleteRecords > 0) {
            logger.warn("[处理警告] 存在{}条不完整记录，请检查相关数据映射", incompleteRecords);
        } else {
            logger.info("[处理成功] 所有记录都已完整匹配");
        }
        
        return result;
    }

    /**
     * 获取科目编码
     * @param subjectName 科目名称
     * @return 科目编码
     */
    private String getSubjectCode(String subjectName) {
        // 使用数据库查询获取课程编号
        return getCourseCode(subjectName);
    }

    /**
     * 创建Workbook对象（支持Excel和CSV格式）
     * @param filePath 文件路径
     * @return Workbook对象
     */
    private Workbook createWorkbook(String filePath) throws IOException {
        String lowerPath = filePath.toLowerCase();
        
        // 如果是CSV文件，转换为Excel格式
        if (lowerPath.endsWith(".csv")) {
            return createWorkbookFromCSV(filePath);
        }
        
        // 处理Excel文件
        try (FileInputStream fis = new FileInputStream(filePath)) {
            // 首先尝试根据文件扩展名判断
            if (lowerPath.endsWith(".xlsx")) {
                return new XSSFWorkbook(fis);
            } else {
                // 对于.xls文件，先尝试作为.xls格式读取
                return new HSSFWorkbook(fis);
            }
        } catch (Exception e) {
            // 如果按扩展名读取失败，尝试另一种格式
            logger.warn("[文件格式检测] 按扩展名读取失败，尝试自动检测格式: {}", e.getMessage());
            
            try (FileInputStream fis = new FileInputStream(filePath)) {
                // 如果之前尝试的是.xls，现在尝试.xlsx
                if (lowerPath.endsWith(".xls")) {
                    logger.info("[文件格式检测] 尝试以XLSX格式读取.xls文件");
                    return new XSSFWorkbook(fis);
                } else {
                    // 如果之前尝试的是.xlsx，现在尝试.xls
                    logger.info("[文件格式检测] 尝试以XLS格式读取.xlsx文件");
                    return new HSSFWorkbook(fis);
                }
            } catch (Exception e2) {
                logger.error("[文件格式检测] 无法识别文件格式: {}", filePath);
                throw new IOException("无法识别文件格式，请确保文件是有效的.xls、.xlsx或.csv文件", e2);
            }
        }
    }
    
    /**
     * 从CSV文件创建Workbook对象
     * @param csvFilePath CSV文件路径
     * @return Workbook对象
     */
    private Workbook createWorkbookFromCSV(String csvFilePath) throws IOException {
        logger.info("[CSV处理] 开始处理CSV文件: {}", csvFilePath);
        
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("CSV Data");
        
        try (FileInputStream fis = new FileInputStream(csvFilePath);
             InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
             CSVReader csvReader = new CSVReader(isr)) {
            
            String[] nextLine;
            int rowNum = 0;
            
            while ((nextLine = csvReader.readNext()) != null) {
                Row row = sheet.createRow(rowNum++);
                for (int i = 0; i < nextLine.length; i++) {
                    Cell cell = row.createCell(i);
                    cell.setCellValue(nextLine[i]);
                }
            }
            
            logger.info("[CSV处理] CSV文件转换完成，共处理 {} 行数据", rowNum);
            
        } catch (Exception e) {
            logger.error("[CSV处理] 处理CSV文件时发生错误: {}", e.getMessage(), e);
            throw new IOException("无法处理CSV文件: " + e.getMessage(), e);
        }
        
        return workbook;
    }

    /**
     * 获取单元格值作为字符串
     * @param cell 单元格
     * @return 字符串值
     */
    private String getCellValueAsString(Cell cell) {
        if (cell == null) {
            return null;
        }
        
        String value;
        switch (cell.getCellType()) {
            case STRING:
                value = cell.getStringCellValue();
                break;
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    value = cell.getDateCellValue().toString();
                } else {
                    value = String.valueOf((long) cell.getNumericCellValue());
                }
                break;
            case BOOLEAN:
                value = String.valueOf(cell.getBooleanCellValue());
                break;
            case FORMULA:
                value = cell.getCellFormula();
                break;
            default:
                return null;
        }
        
        // 去除字符串中的所有空格，特别是教师姓名中的空格
        if (value != null) {
            value = value.replaceAll("\\s+", "");
        }
        
        return value;
    }

    /**
     * 将列名转换为索引
     * @param column 列名（如A, B, C等）
     * @return 列索引（从0开始）
     */
    private int convertColumnToIndex(String column) {
        if (column == null || column.isEmpty()) {
            return 0;
        }
        
        column = column.toUpperCase();
        int result = 0;
        for (int i = 0; i < column.length(); i++) {
            result = result * 26 + (column.charAt(i) - 'A' + 1);
        }
        return result - 1;
    }

    /**
     * 将列索引转换为列名
     * @param columnIndex 列索引（从0开始）
     * @return 列名（如A, B, C等）
     */
    private String getColumnName(int columnIndex) {
        StringBuilder result = new StringBuilder();
        while (columnIndex >= 0) {
            result.insert(0, (char) ('A' + columnIndex % 26));
            columnIndex = columnIndex / 26 - 1;
        }
        return result.toString();
    }

    /**
     * 验证是否为有效的文件格式（支持Excel和CSV）
     * @param file 文件
     * @return 是否有效
     */
    private boolean isValidExcelFile(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            return false;
        }
        
        String fileName = file.getOriginalFilename();
        if (fileName == null) {
            return false;
        }
        
        String lowerFileName = fileName.toLowerCase();
        return lowerFileName.endsWith(".xls") || 
               lowerFileName.endsWith(".xlsx") || 
               lowerFileName.endsWith(".csv");
    }

    /**
     * 创建必要的目录
     */
    private void createDirectories() throws IOException {
        Files.createDirectories(Paths.get(uploadDir));
        Files.createDirectories(Paths.get(outputDir));
    }

    /**
     * 保存上传的文件
     * @param file 上传的文件
     * @return 保存的文件名
     */
    private String saveUploadedFile(MultipartFile file) throws IOException {
        String originalFileName = file.getOriginalFilename();
        String fileName = System.currentTimeMillis() + "_" + originalFileName;
        Path filePath = Paths.get(uploadDir, fileName);
        
        try (InputStream inputStream = file.getInputStream()) {
            Files.copy(inputStream, filePath, StandardCopyOption.REPLACE_EXISTING);
        }
        
        return fileName;
    }

    /**
     * 生成输出文件（支持Excel和CSV格式）
     * @param data 处理后的数据
     * @param originalFileName 原始文件名
     * @param isStrictMode 是否为严格模式
     * @return 输出文件名
     */
    public String generateOutputFile(List<Map<String, Object>> data, String originalFileName, boolean isStrictMode) throws IOException {
        // 根据原始文件扩展名确定输出格式
        String lowerFileName = originalFileName.toLowerCase();
        if (lowerFileName.endsWith(".csv")) {
            return generateCSVOutputFile(data, originalFileName, isStrictMode);
        } else {
            return generateExcelOutputFile(data, originalFileName, isStrictMode);
        }
    }
    
    /**
     * 生成Excel格式输出文件
     * @param data 处理后的数据
     * @param originalFileName 原始文件名
     * @param isStrictMode 是否为严格模式
     * @return 输出文件名
     */
    private String generateExcelOutputFile(List<Map<String, Object>> data, String originalFileName, boolean isStrictMode) throws IOException {
        logger.info("[输出文件生成开始] 开始生成输出文件，数据条数: {}", data.size());
        
        if (data.isEmpty()) {
            logger.warn("[输出文件生成警告] 没有数据需要输出");
            throw new IllegalArgumentException("没有数据可以生成输出文件");
        }
        
        // 确保输出目录存在
        logger.debug("[步骤1] 创建输出目录: {}", outputDir);
        Files.createDirectories(Paths.get(outputDir));
        
        String outputFileName = "processed_" + System.currentTimeMillis() + "_" + originalFileName;
        String outputFilePath = Paths.get(outputDir, outputFileName).toString();
        
        logger.info("[文件路径] 输出文件将保存到: {}", outputFilePath);
        
        // 声明计数变量
        int validRowCount = 0;
        int filteredCount = 0;
        
        try (Workbook workbook = new XSSFWorkbook();
             FileOutputStream fos = new FileOutputStream(outputFilePath)) {
            
            logger.debug("[步骤2] 创建Excel工作簿和工作表");
            Sheet sheet = workbook.createSheet("处理结果");
            
            // 创建标题行（按照用户要求的格式）
            logger.debug("[步骤3] 创建表头");
            Row headerRow = sheet.createRow(0);
            headerRow.createCell(0).setCellValue("教师编号*");
            headerRow.createCell(1).setCellValue("教师姓名");
            headerRow.createCell(2).setCellValue("课程编号*");
            headerRow.createCell(3).setCellValue("课程名称");
            headerRow.createCell(4).setCellValue("班级编号*");
            headerRow.createCell(5).setCellValue("班级名称*");
            headerRow.createCell(6).setCellValue("人数上限*");
            headerRow.createCell(7).setCellValue("人数下限*");
            headerRow.createCell(8).setCellValue("开始日期*");
            headerRow.createCell(9).setCellValue("结束日期*");
            headerRow.createCell(10).setCellValue("备注");
            
            // 填充数据 - 只输出有课程编号的数据
             logger.debug("[步骤4] 填充数据行（过滤无课程编号的数据）");
            
            for (int i = 0; i < data.size(); i++) {
                Map<String, Object> record = data.get(i);
                
                String teacherName = record.get("teacherName") != null ? record.get("teacherName").toString() : "";
                String subjectName = record.get("subject") != null ? record.get("subject").toString() : "";
                String className = record.get("className") != null ? record.get("className").toString() : "";
                
                // 使用已经获取的编号
                String teacherCode = (String) record.getOrDefault("teacherCode", "");
                String courseCode = (String) record.getOrDefault("subjectCode", "");
                String classCode = (String) record.getOrDefault("classCode", "");
                
                // 过滤条件：只输出有课程编号的数据，排除课前准备、午读类课程
                if (courseCode == null || courseCode.trim().isEmpty() || 
                    subjectName.contains("课前准备") || subjectName.contains("午读")) {
                    logger.debug("[数据过滤] 跳过记录: 教师={}, 科目={}, 班级={}, 原因: 无课程编号或为排除类型", 
                               teacherName, subjectName, className);
                    filteredCount++;
                    continue;
                }
                
                Row row = sheet.createRow(validRowCount + 1);
                logger.debug("[数据行{}] 处理记录: 教师={}, 科目={}, 班级={}", validRowCount + 1, teacherName, subjectName, className);
                
                // 填充单元格
                row.createCell(0).setCellValue(teacherCode);
                row.createCell(1).setCellValue(teacherName);
                row.createCell(2).setCellValue(courseCode);
                
                // 课程名称处理：严格模式使用原始名称，普通模式进行格式化
                String finalSubjectName;
                if (isStrictMode) {
                    // 严格模式：直接使用原始课程名称，不进行格式化
                    finalSubjectName = subjectName;
                    logger.debug("[严格模式] 使用原始课程名称: {}", finalSubjectName);
                } else {
                    // 普通模式：格式化课程名称（根据班级动态添加年级标识）
                    logger.debug("[课程名称格式化调试] 原始课程名称: {}, 班级名称: {}", subjectName, className);
                    finalSubjectName = courseMatchingService.formatSubjectName(subjectName, className);
                    logger.debug("[课程名称格式化调试] 格式化后课程名称: {}", finalSubjectName);
                }
                row.createCell(3).setCellValue(finalSubjectName);
                
                row.createCell(4).setCellValue(classCode);
                // 使用转换后的班级名称
                String outputClassName;
                if (isStrictMode) {
                    // 严格模式：直接使用record中的className（已经是@后的部分）
                    outputClassName = (String) record.getOrDefault("className", className);
                    logger.debug("[严格模式输出] 使用解析后的班级名称: {}", outputClassName);
                } else {
                    // 普通模式：使用转换后的班级名称
                    outputClassName = (String) record.getOrDefault("convertedClassName", className);
                }
                
                row.createCell(5).setCellValue(outputClassName);
                // 添加默认值列
                row.createCell(6).setCellValue(60);  // 人数上限默认60
                row.createCell(7).setCellValue(30);  // 人数下限默认30
                row.createCell(8).setCellValue("2024-9-2");   // 开始日期默认2024-9-2
                row.createCell(9).setCellValue("2025-02-10"); // 结束日期默认2025-02-10
                row.createCell(10).setCellValue(""); // 备注为空
                
                validRowCount++;
            }
            
            logger.info("[数据填充完成] 原始记录: {} 条, 有效输出: {} 条, 过滤掉: {} 条", data.size(), validRowCount, filteredCount);
            
            // 自动调整列宽
            logger.debug("[步骤5] 调整列宽");
            for (int i = 0; i < 11; i++) {
                sheet.autoSizeColumn(i);
            }
             
             logger.debug("[步骤6] 写入文件到磁盘");
             workbook.write(fos);
             
             // 确保文件已写入磁盘
             fos.flush();
             
             logger.info("[输出文件生成成功] 文件已成功写入: {}", outputFilePath);
         } catch (IOException e) {
             logger.error("[输出文件生成失败] 写入文件时发生错误: {}", e.getMessage(), e);
             throw e;
         }
         
         logger.info("[输出文件生成完成] 文件名: {}, 有效记录数: {}", outputFileName, validRowCount);
         return outputFileName;
     }
     
     /**
      * 生成CSV格式输出文件
      * @param data 处理后的数据
      * @param originalFileName 原始文件名
      * @param isStrictMode 是否为严格模式
      * @return 输出文件名
      */
     private String generateCSVOutputFile(List<Map<String, Object>> data, String originalFileName, boolean isStrictMode) throws IOException {
         logger.info("[CSV输出文件生成开始] 开始生成CSV输出文件，数据条数: {}", data.size());
         
         if (data.isEmpty()) {
             logger.warn("[CSV输出文件生成警告] 没有数据需要输出");
             throw new IllegalArgumentException("没有数据可以生成输出文件");
         }
         
         // 确保输出目录存在
         logger.debug("[步骤1] 创建输出目录: {}", outputDir);
         Files.createDirectories(Paths.get(outputDir));
         
         String outputFileName = "processed_" + System.currentTimeMillis() + "_" + originalFileName;
         String outputFilePath = Paths.get(outputDir, outputFileName).toString();
         
         logger.info("[文件路径] CSV输出文件将保存到: {}", outputFilePath);
         
         // 声明计数变量
         int validRowCount = 0;
         int filteredCount = 0;
         
         try (FileOutputStream fos = new FileOutputStream(outputFilePath);
              OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
              CSVWriter csvWriter = new CSVWriter(osw)) {
             
             logger.debug("[步骤2] 创建CSV写入器");
             
             // 写入BOM以支持Excel正确显示中文
             fos.write(new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF});
             
             // 创建标题行
             logger.debug("[步骤3] 写入CSV表头");
             String[] headers = {
                 "教师编号*", "教师姓名", "课程编号*", "课程名称", "班级编号*", 
                 "班级名称*", "人数上限*", "人数下限*", "开始日期*", "结束日期*", "备注"
             };
             csvWriter.writeNext(headers);
             
             // 填充数据 - 只输出有课程编号的数据
             logger.debug("[步骤4] 填充CSV数据行（过滤无课程编号的数据）");
             
             for (int i = 0; i < data.size(); i++) {
                 Map<String, Object> record = data.get(i);
                 
                 String teacherName = record.get("teacherName") != null ? record.get("teacherName").toString() : "";
                 String subjectName = record.get("subject") != null ? record.get("subject").toString() : "";
                 String className = record.get("className") != null ? record.get("className").toString() : "";
                 
                 // 使用已经获取的编号
                 String teacherCode = (String) record.getOrDefault("teacherCode", "");
                 String courseCode = (String) record.getOrDefault("subjectCode", "");
                 String classCode = (String) record.getOrDefault("classCode", "");
                 
                 // 过滤条件：只输出有课程编号的数据，排除课前准备、午读类课程
                 if (courseCode == null || courseCode.trim().isEmpty() || 
                     subjectName.contains("课前准备") || subjectName.contains("午读")) {
                     logger.debug("[数据过滤] 跳过记录: 教师={}, 科目={}, 班级={}, 原因: 无课程编号或为排除类型", 
                                teacherName, subjectName, className);
                     filteredCount++;
                     continue;
                 }
                 
                 logger.debug("[数据行{}] 处理记录: 教师={}, 科目={}, 班级={}", validRowCount + 1, teacherName, subjectName, className);
                 
                 // 课程名称处理：严格模式使用原始名称，普通模式进行格式化
                 String finalSubjectName;
                 if (isStrictMode) {
                     // 严格模式：直接使用原始课程名称，不进行格式化
                     finalSubjectName = subjectName;
                     logger.debug("[严格模式] 使用原始课程名称: {}", finalSubjectName);
                 } else {
                     // 普通模式：格式化课程名称（根据班级动态添加年级标识）
                     logger.debug("[课程名称格式化调试] 原始课程名称: {}, 班级名称: {}", subjectName, className);
                     finalSubjectName = courseMatchingService.formatSubjectName(subjectName, className);
                     logger.debug("[课程名称格式化调试] 格式化后课程名称: {}", finalSubjectName);
                 }
                 
                 // 使用转换后的班级名称
                 String outputClassName;
                 if (isStrictMode) {
                     // 严格模式：直接使用record中的className（已经是@后的部分）
                     outputClassName = (String) record.getOrDefault("className", className);
                     logger.debug("[严格模式输出] 使用解析后的班级名称: {}", outputClassName);
                 } else {
                     // 普通模式：使用转换后的班级名称
                     outputClassName = (String) record.getOrDefault("convertedClassName", className);
                 }
                 
                 // 创建数据行
                 String[] rowData = {
                     teacherCode,
                     teacherName,
                     courseCode,
                     finalSubjectName,
                     classCode,
                     outputClassName,
                     "60",  // 人数上限默认60
                     "30",  // 人数下限默认30
                     "2024-9-2",   // 开始日期默认2024-9-2
                     "2025-02-10", // 结束日期默认2025-02-10
                     ""     // 备注为空
                 };
                 
                 csvWriter.writeNext(rowData);
                 validRowCount++;
             }
             
             logger.info("[CSV数据填充完成] 原始记录: {} 条, 有效输出: {} 条, 过滤掉: {} 条", data.size(), validRowCount, filteredCount);
             
             logger.debug("[步骤5] 刷新CSV写入器");
             csvWriter.flush();
             
             logger.info("[CSV输出文件生成成功] 文件已成功写入: {}", outputFilePath);
             
         } catch (IOException e) {
             logger.error("[CSV输出文件生成失败] 写入文件时发生错误: {}", e.getMessage(), e);
             throw e;
         }
         
         logger.info("[CSV输出文件生成完成] 文件名: {}, 有效记录数: {}", outputFileName, validRowCount);
         return outputFileName;
     }

    /**
     * 获取教师编号（从数据库查询）
     * @param teacherName 教师姓名
     * @return 教师编号
     */
    private String getTeacherCode(String teacherName) {
        if (teacherName == null || teacherName.trim().isEmpty()) {
            logger.warn("[教师匹配失败] 教师姓名为空");
            return "";
        }
        
        logger.info("[教师匹配开始] 教师姓名: {}", teacherName);
        
        try {
            // 先尝试按完整姓名查找
            logger.debug("[步骤1] 尝试完整姓名查找: {}", teacherName);
            Teacher teacher = teacherDao.findByFullName(teacherName);
            if (teacher != null && teacher.getTrNum() != null) {
                logger.info("[教师匹配成功] 完整姓名匹配 - 教师: {} -> 编号: {}", teacherName, teacher.getTrNum());
                return teacher.getTrNum();
            }
            
            // 如果找不到，记录详细的失败信息
            logger.warn("[教师匹配失败] 数据库中未找到教师: {}", teacherName);
            logger.warn("[建议] 请检查以下内容: 1.数据库中是否存在该教师 2.教师姓名是否正确 3.是否需要添加该教师到数据库");
            return "";
        } catch (Exception e) {
            logger.error("[教师匹配异常] 查询教师编号时发生错误 - 教师: {}, 错误: {}", teacherName, e.getMessage(), e);
            return "";
        }
    }

    /**
     * 获取课程编号（从数据库查询）
     * @param subjectName 课程名称
     * @return 课程编号
     */
    private String getCourseCode(String subjectName) {
        if (subjectName == null || subjectName.trim().isEmpty()) {
            return "";
        }
        
        try {
            // 首先尝试从数据库查找
            Course course = courseDao.findByName(subjectName);
            if (course != null && course.getCourNum() != null) {
                return course.getCourNum();
            }
            
            // 尝试模糊匹配数据库中的课程
            List<Course> allCourses = courseDao.findAll();
            for (Course c : allCourses) {
                if (c.getCourName() != null && 
                    (c.getCourName().contains(subjectName) || subjectName.contains(c.getCourName()))) {
                    logger.info("使用模糊匹配获取课程编号: {} -> {} (匹配: {})", subjectName, c.getCourNum(), c.getCourName());
                    return c.getCourNum();
                }
            }
            
            // 如果找不到，记录日志但不抛出异常（保持原有行为）
            logger.warn("未找到课程: {}", subjectName);
            return "";
        } catch (Exception e) {
            logger.error("查询课程编号时发生错误: {}", subjectName, e);
            return "";
        }
    }
    
    // getCourseCodeWithGrade方法已重构到CourseMatchingService中
    
    // 以下方法已重构到其他服务类：
    // - extractGradeFromClassName -> GradeExtractionService
    // - extractGradeIdentifier -> GradeExtractionService
    
    /**
     * 格式化课程名称（根据班级名称添加年级标识）
     * 已废弃：直接使用CourseMatchingService的formatSubjectName方法
     * @param subjectName 原始课程名称
     * @param className 班级名称
     * @return 格式化后的课程名称
     */
    @Deprecated
    private String formatSubjectName(String subjectName, String className) {
        // 直接调用CourseMatchingService的方法，确保格式一致
        return courseMatchingService.formatSubjectName(subjectName, className);
    }
    
  

    /**
     * 清理临时文件
     * @param filePath 文件路径
     */
    private void cleanupTempFile(String filePath) {
        try {
            Files.deleteIfExists(Paths.get(filePath));
        } catch (IOException e) {
            logger.warn("清理临时文件失败: {}", filePath, e);
        }
    }

    /**
     * 获取文件上传状态
     * @return 状态信息
     */
    public Map<String, Object> getUploadStatus() {
        Map<String, Object> status = new HashMap<>();

        try {
            Path uploadDir = Paths.get(UPLOAD_DIR);
            Path outputDir = Paths.get(OUTPUT_DIR);

            boolean uploadDirExists = Files.exists(uploadDir);
            boolean outputDirExists = Files.exists(outputDir);

            status.put("uploadDirExists", uploadDirExists);
            status.put("outputDirExists", outputDirExists);
            status.put("uploadDir", uploadDir.toAbsolutePath().toString());
            status.put("outputDir", outputDir.toAbsolutePath().toString());

            if (uploadDirExists) {
                long uploadFileCount = Files.list(uploadDir).count();
                status.put("uploadFileCount", uploadFileCount);
            }

            if (outputDirExists) {
                long outputFileCount = Files.list(outputDir).count();
                status.put("outputFileCount", outputFileCount);
            }

        } catch (IOException e) {
            logger.error("获取上传状态时发生错误", e);
            status.put("error", e.getMessage());
        }

        return status;
    }

    /**
     * 预览Excel文件内容
     * @param fileName 文件名
     * @return 预览数据
     */
    public Map<String, Object> previewExcelFile(String fileName) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 构建文件路径
            String filePath = outputDir + File.separator + fileName;
            Path file = Paths.get(filePath);
            
            if (!Files.exists(file)) {
                result.put("success", false);
                result.put("message", "文件不存在: " + fileName);
                return result;
            }
            
            List<Map<String, Object>> previewData = new ArrayList<>();
            
            try (Workbook workbook = createWorkbook(filePath)) {
                Sheet sheet = workbook.getSheetAt(0); // 读取第一个工作表
                
                int maxRows = Math.min(100, sheet.getLastRowNum() + 1); // 最多预览100行
                
                // 获取表头
                Row headerRow = sheet.getRow(0);
                List<String> headers = new ArrayList<>();
                if (headerRow != null) {
                    int lastCellNum = headerRow.getLastCellNum();
                    for (int i = 0; i < lastCellNum; i++) {
                        Cell cell = headerRow.getCell(i);
                        String header = getCellValueAsString(cell);
                        headers.add(header != null ? header : "列" + (i + 1));
                    }
                }
                
                // 读取数据行
                for (int rowIndex = 0; rowIndex < maxRows; rowIndex++) {
                    Row row = sheet.getRow(rowIndex);
                    if (row == null) continue;
                    
                    Map<String, Object> rowData = new HashMap<>();
                    int lastCellNum = Math.max(headers.size(), row.getLastCellNum());
                    
                    for (int cellIndex = 0; cellIndex < lastCellNum; cellIndex++) {
                        Cell cell = row.getCell(cellIndex);
                        String cellValue = getCellValueAsString(cell);
                        String columnName = cellIndex < headers.size() ? headers.get(cellIndex) : "列" + (cellIndex + 1);
                        rowData.put(columnName, cellValue != null ? cellValue : "");
                    }
                    
                    previewData.add(rowData);
                }
                
                result.put("success", true);
                result.put("data", previewData);
                result.put("totalRows", sheet.getLastRowNum() + 1);
                result.put("previewRows", previewData.size());
                result.put("message", "预览成功，显示前" + previewData.size() + "行数据");
                
            }
            
        } catch (Exception e) {
            logger.error("预览Excel文件时发生错误: {}", fileName, e);
            result.put("success", false);
            result.put("message", "预览文件失败: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 清理文件
     * @param keepDays 保留天数
     * @return 清理结果
     */
    public Map<String, Object> cleanupFiles(int keepDays) {
        Map<String, Object> result = new HashMap<>();
        int deletedCount = 0;
        
        try {
            Path uploadPath = Paths.get(uploadDir);
            Path outputPath = Paths.get(outputDir);
            
            // 确保目录存在
            Files.createDirectories(uploadPath);
            Files.createDirectories(outputPath);
            
            long cutoffTime = System.currentTimeMillis() - (keepDays * 24L * 60L * 60L * 1000L);
            
            // 清理上传目录
            deletedCount += cleanupDirectory(uploadPath, cutoffTime);
            
            // 清理输出目录
            deletedCount += cleanupDirectory(outputPath, cutoffTime);
            
            result.put("success", true);
            result.put("message", "文件清理完成");
            result.put("deletedCount", deletedCount);
            result.put("keepDays", keepDays);
            
        } catch (Exception e) {
            logger.error("清理文件时发生错误", e);
            result.put("success", false);
            result.put("message", "文件清理失败: " + e.getMessage());
            result.put("deletedCount", deletedCount);
        }
        
        return result;
    }
    
    /**
     * 清理指定目录中的旧文件
     * @param directory 目录路径
     * @param cutoffTime 截止时间
     * @return 删除的文件数量
     */
    private int cleanupDirectory(Path directory, long cutoffTime) throws IOException {
        int deletedCount = 0;
        
        if (!Files.exists(directory)) {
            return deletedCount;
        }
        
        try (var stream = Files.list(directory)) {
            for (Path file : stream.toList()) {
                if (Files.isRegularFile(file)) {
                    long lastModified = Files.getLastModifiedTime(file).toMillis();
                    if (lastModified < cutoffTime) {
                        try {
                            Files.delete(file);
                            deletedCount++;
                            logger.info("删除文件: {}", file.getFileName());
                        } catch (IOException e) {
                            logger.warn("删除文件失败: {}, 错误: {}", file.getFileName(), e.getMessage());
                        }
                    }
                }
            }
        }
        
        return deletedCount;
    }

}